<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import dayjs from 'dayjs'
import type { SelectorPickerOnChangeEvent } from '@uni-helper/uni-app-types'
import type { UniCalendarOnChangeEvent } from '@uni-helper/uni-ui-types'
import { chunk } from 'lodash-es'
import { wait } from '@/utils/utils'

const props = defineProps({
    date: {
        type: String,
        default: '',
    },
    selected: {
        type: Array,
        default: () => ([]),
    },
})

const emits = defineEmits(['update:date', 'click'])

const todayDate = ref('2024-10-01')

const weekList = ref(['日', '一', '二', '三', '四', '五', '六'])
const monthList = ref<string[]>([] as string[])
const chunkMonthList = ref<string[][]>([] as string[][])
const current = ref(0)

const toggle = ref(true)

const showSelected = computed(() => {
    return (item: string) => {
        return props.selected?.includes(item)
    }
})

const setCalendarSelected = computed(() => {
    return props.selected?.map((item) => {
        return {
            date: item,
            inof: '打卡',
        }
    })
})

watch(() => props.date, (val) => {
    todayDate.value = val
    if (val)
        createDayList()
}, {
    immediate: true,
})

/**
 * 底部picker弹出来的日期选择改变时触发的回调函数
 *
 * @param e 选择器变化事件对象
 * @param e.detail.value 选择的日期值
 */
function onDateChange(e: SelectorPickerOnChangeEvent) {
    const value = e.detail.value
    todayDate.value = dayjs(value).format('YYYY-MM-DD')
    createDayList()
    emitData()
}

/**
 * uni自带日历切换日期
 *
 * @param e UniCalendarOnChangeEvent 日历变化事件对象
 */
function onCalendarChange(e: UniCalendarOnChangeEvent) {
    todayDate.value = e.fulldate
    createDayList()
    emitData()
}

/**
 * 当日期发生改变时触发此函数
 *
 * @param day 日期字符串
 */
function onDayChange(day: string) {
    todayDate.value = day
    // createDayList()
    emitData()
}

function emitData() {
    emits('update:date', todayDate.value)
    emits('click', todayDate.value)
}

// 显示周还是完整的日历  true周 false日历
function onToggle() {
    toggle.value = !toggle.value
}

// 计算当月日历的天数，并拆成周，用于swiper展示
async function createDayList() {
    // 当月一共有多少天
    const totalDay = dayjs(todayDate.value).endOf('month').date()
    monthList.value = []
    for (let i = 1; i <= totalDay; i++) {
        const curYear = dayjs(todayDate.value).year()
        const curMonth = dayjs(todayDate.value).month() + 1
        const date = dayjs(`${curYear}-${curMonth}-${i}`).format('YYYY-MM-DD')
        monthList.value.push(date)
    }
    // 当月第一天是周几
    const firstDayWeek = dayjs(todayDate.value).startOf('month').format('d')
    // 如果第一天不是星期日，则需要向前补全整个星期，补全需要知道上一个月最后一天是多少号
    const lastMonthLastDay = dayjs(todayDate.value).subtract(1, 'month').endOf('month').date()

    if (firstDayWeek !== '0') {
        for (let i = 0; i < Number(firstDayWeek); i++) {
            const curYear = dayjs(todayDate.value).year()
            const curMonth = dayjs(todayDate.value).month()
            const date = dayjs(`${curYear}-${curMonth}-${Number(lastMonthLastDay) - i}`).format('YYYY-MM-DD')
            monthList.value.unshift(date)
        }
    }
    // 如果总天数模上7余数不是0，则需要向后补全整个星期
    const restDay = monthList.value.length % 7
    if (restDay !== 0) {
        for (let i = 1; i <= 7 - restDay; i++) {
            const curYear = dayjs(todayDate.value).year()
            const curMonth = dayjs(todayDate.value).month() + 2
            const date = dayjs(`${curYear}-${curMonth}-${i}`).format('YYYY-MM-DD')
            monthList.value.push(date)
        }
    }
    chunkMonthList.value = chunk(monthList.value, 7)
    await wait(100)
    calcSwiperCurrent()
}
// 根据当天日期计算当前swiper的current值，默认展示含有当天日期的那一周
function calcSwiperCurrent() {
    current.value = chunkMonthList.value.findIndex(i => i.includes(todayDate.value))
}
</script>

<template>
    <view class="bg-white">
        <picker mode="date" :value="todayDate" @change="onDateChange">
            <view class="flex items-center py-10rpx text-56rpx font-bold">
                <view>{{ todayDate }}</view>
                <view
                    class="ml-20rpx mt-5rpx h-0 w-0 border-10rpx border-b-transparent border-l-transparent border-r-transparent border-t-black border-solid" />
            </view>
        </picker>
        <view v-if="toggle" class="my-30rpx">
            <view class="grid grid-cols-7">
                <view v-for="(i, index) in weekList" :key="index">
                    <view class="text-center lh-60rpx">{{ i }}</view>
                </view>
            </view>
            <swiper class="h-80rpx" :current="current" :autoplay="false">
                <swiper-item v-for="(i, index) in chunkMonthList" :key="index" class="h-full">
                    <view class="grid grid-cols-7 h-full">
                        <view v-for="(item, idx) in i" :key="idx">
                            <view class="text-center lh-60rpx"
                                  :class="{ 'text-primary bg-primary bg-op-10': todayDate === item }"
                                  @click="onDayChange(item)">
                                {{ dayjs(item).format('D') }}
                            </view>
                            <view v-show="showSelected(item)"
                                  class="mx-auto h-10rpx w-10rpx rounded-full bg-primary" />
                        </view>
                    </view>
                </swiper-item>
            </swiper>
        </view>
        <view v-else class="mt-30rpx">
            <uni-calendar :date="todayDate" :selected="setCalendarSelected" :insert="true" @change="onCalendarChange" />
        </view>
        <view class="mt-5rpx flex justify-center py-20rpx" @click="onToggle">
            <view class="h-8rpx w-48rpx rounded-full bg-#E3E4E5" />
        </view>
    </view>
</template>
